package test.wph;

import java.util.Deque;
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description
 * @Author Firenut
 * @Date 2023-08-21 19:24
 */
class BoundedBlockingQueue {
    LinkedList<Integer> queue;

    // 队列的最大值
    int capacity;

    // 存放当前队列元素个数
    // (为了保证拿到的队列长度是最新的不能直接用queue.get(),会有线程安全的问题)
    volatile int size;

    ReentrantLock lock = new ReentrantLock();
    Condition emptyCond;
    Condition fullCond;

    public BoundedBlockingQueue(int capacity) {
        this.queue = new LinkedList<>();
        this.capacity = capacity;
        size = 0;
        lock = new ReentrantLock();
        emptyCond = lock.newCondition();
        fullCond = lock.newCondition();
    }

    public void enqueue(int element) throws InterruptedException {
        lock.lock();
        try {
            while (size() == capacity) {
                // 阻塞生产者线程,轮询判断队列容量
                fullCond.await();
            }
            queue.addLast(element);
            // 随机唤醒一个消费者线程
            emptyCond.signal();
        } finally {
            lock.unlock();
        }
    }

    public int dequeue() throws InterruptedException {
        lock.lock();
        try {
            while (size() == 0) {
                emptyCond.await();
            }
            int val = queue.removeLast();
            fullCond.await();
            return val;
        } finally {
            lock.unlock();
        }
    }

    // 获取队列当前长度
    public int size() {
        return size;
    }
}